#pragma once

#include <rocksdb/db.h>
#include <rocksdb/options.h>
#include <rocksdb/slice.h>
#include <rocksdb/status.h>

#include <memory>

#include "redis/store/common.h"
#include "redis/store/redis_zsets.h"

class Redis {
 public:
  Redis();
  ~Redis();

  rocksdb::Status Open(const std::string& db_path,
                       const rocksdb::Options& options);
  rocksdb::Status CreateColumnFamilies();

  rocksdb::Status ZAdd(
      const rocksdb::Slice& key, const std::vector<ScoreMember>& score_members,
      int32_t* ret,
      const std::shared_ptr<rocksdb::Transaction>& transaction = nullptr);
  rocksdb::Status ZRank(
      const rocksdb::Slice& key, const rocksdb::Slice& member, int32_t* rank,
      const std::shared_ptr<rocksdb::Transaction>& transaction = nullptr);
  rocksdb::Status ZRange(
      const rocksdb::Slice& key, int32_t start, int32_t stop,
      std::vector<ScoreMember>* score_members,
      const std::shared_ptr<rocksdb::Transaction>& transaction = nullptr);

  std::shared_ptr<rocksdb::Transaction> Multi();
  rocksdb::Status Exec(
      const std::shared_ptr<rocksdb::Transaction>& transaction);

  rocksdb::Status GetProperty(const std::string& property, uint64_t* out);
  rocksdb::Status ScanKeyNum(KeyInfo* key_info);
  rocksdb::Status ScanKeys(const std::string& pattern,
                           std::vector<std::string>* keys);
  rocksdb::Status Expire(const rocksdb::Slice& key, int32_t ttl);
  rocksdb::Status Del(const rocksdb::Slice& key);
  bool Scan(const std::string& start_key, const std::string& pattern,
            std::vector<std::string>* keys, int64_t* count,
            std::string* next_key);

 private:
  rocksdb::Options options_;
  std::string db_path_;

  std::shared_ptr<rocksdb::TransactionDB> transcation_db_;
  std::vector<rocksdb::ColumnFamilyHandle*> cf_handles_;
  std::vector<rocksdb::ColumnFamilyDescriptor> column_families_;
  std::unique_ptr<RedisZSets> zsets_;

  rocksdb::WriteOptions write_options_;
  rocksdb::ReadOptions read_options_;
  rocksdb::CompactRangeOptions compact_range_options_;
};
